/*
 * Troika Reference Implementation
 * Copyright (C) 2018 Cybercrypt A/S <www.cyber-crypt.com>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef TROIKA_H
#define TROIKA_H

typedef unsigned char Trit; /* Stores 0,1,2 in a byte. */
typedef unsigned char Tryte; /* Stores 0,...,26 in a byte. */

#define NUM_ROUNDS 24
#define TROIKA_RATE 243

class Troika {
protected:
	virtual void TroikaSqueeze(Trit *hash, unsigned long long hash_length, unsigned int rate, Trit *state, unsigned long long num_rounds);
	virtual void TroikaAbsorb(Trit *state, unsigned int rate, const Trit *message, unsigned long long message_length, unsigned long long num_rounds);

	void SubTrytes(Trit *state);
	void ShiftRows(Trit *state);
	void ShiftLanes(Trit *state);
	void AddColumnParity(Trit *state);
	void AddRoundConstant(Trit *state, int round);
	virtual void TroikaPermutation(Trit *state, unsigned long long num_rounds);

	/*
	 * Prints the state in a nice format.
	 *
	 * @param state Pointer to the state which is printed.
	 */
	void PrintTroikaSlice(Trit *state, int slice);
	void PrintTroikaState(Trit *state);

public:
	void print(Trit *state);
	/*
	 * Evaluates the Troika hash function on the input.
	 *
	 * @param out    Pointer to the output buffer.
	 * @param outlen Length of the output to be generated in trits.
	 * @param input  Pointer to the input buffer.
	 * @param inlen  Length of the input buffer in trits.
	 *
	 */
	virtual void doTroika(Trit *out, unsigned long long outlen,
				const Trit *in, unsigned long long inlen);

	/*
	 * Evaluates the Troika hash function on the input with a variable
	 * number of rounds of the permutation.
	 *
	 * @param out    Pointer to the output buffer.
	 * @param outlen Length of the output to be generated in trits.
	 * @param input  Pointer to the input buffer.
	 * @param inlen  Length of the input buffer in trits.
	 * @param rounds Number of rounds used for the permutation.
	 *
	 */
	virtual void doTroikaVarRounds(Trit *out, unsigned long long outlen,
						 const Trit *in, unsigned long long inlen,
						 unsigned long long num_rounds);
};



#endif
